﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ZenHR.AttData.Collection.TaskQueue
{
    /// <summary>
    /// 任务队列
    /// </summary>
    public class TaskQueue<T> : ITaskQueue<T>, IDisposable
    {
        /// <summary>
        /// 内置队列
        /// </summary>
        private ConcurrentDictionary<int, IList<T>> taskQueues;
        /// <summary>
        /// 分区大小
        /// </summary>
        private int PartitionSize;
        /// <summary>
        /// 默认index为0
        /// </summary>
        private int Index = 0;
        /// <summary>
        /// 默认处理偏移
        /// </summary>
        private int OffSet = 0;
        /// <summary>
        /// 内置锁
        /// </summary>
        private object Lock = new object();
        /// <summary>
        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="PartitionSize">分区大小，默认分区大小为8 </param>
        public TaskQueue(int PartitionSize = 8)
        {
            taskQueues = new ConcurrentDictionary<int, IList<T>>();
            this.PartitionSize = PartitionSize;
            List<T> ts = new List<T>();
            taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
        }
        /// <summary>
        /// 增加一个对象
        /// </summary>
        /// <param name="t"></param>
        public void Add(T t)
        {
            lock (Lock)
            {
                IList<T> ts;
                if (taskQueues.TryGetValue(Index, out ts))
                {
                    if (ts.Count < PartitionSize)
                    {
                        ts.Add(t);
                        taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
                    }
                    else //超出区域范围，则新建区
                    {
                        Index++;
                        IList<T> ts1 = new List<T>();
                        ts1.Add(t);
                        taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
                    }
                }
                else
                {
                    IList<T> ts1 = new List<T>();
                    ts1.Add(t);
                    taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
                }
            }
        }

        /// <summary>
        /// 获取一个分组队列
        /// </summary>
        /// <returns></returns>
        public IList<T> GetQueue()
        {
            lock (Lock)
            {
                IList<T> ts;
                if (taskQueues.TryGetValue(OffSet, out ts))
                {
                    if (OffSet == Index)//如果直接获取一个能用的，那就新建区为新区
                    {
                        Index++;
                    }
                    return ts;
                }
                return null;
            }
        }
        /// <summary>
        /// 是否阻塞增加
        /// </summary>
        /// <returns></returns>
        public bool IsWaitAdd()
        {
            lock (Lock)
            {
                if (OffSet != Index)
                {
                    return true;
                }
                return false;
            }
        }
        /// <summary>
        /// 当前队列完成
        /// </summary>
        public void Complete()
        {
            lock (Lock)
            {
                IList<T> ts;
                taskQueues.TryRemove(OffSet, out ts);
                if (OffSet < Index)
                {
                    OffSet++;
                }
            }
        }

        public void Dispose()
        {
            if (taskQueues != null)
            {
                taskQueues.Clear();
                taskQueues = null;
            }
        }
    }
}
